package com.campus.chat.controller;

import com.alibaba.fastjson.JSON;
import com.campus.common.domain.Message;
import com.campus.common.enums.OnlineStatusEnum;
import com.campus.common.service.UserInfoService;
import com.campus.common.utils.JwtUtil;
import com.campus.common.utils.RedisCache;
import jakarta.annotation.Resource;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@Slf4j
@ServerEndpoint("/chat/{token}")
public class WebSocket {
    private static UserInfoService userInfoService;
    private static RedisCache redisCache;

    //用线程安全的map来保存当前用户
    public static final Map<Integer, Session> onlineUsers = new ConcurrentHashMap<>();
    // private static final CopyOnWriteArraySet<WebSocket> chatServers =new CopyOnWriteArraySet<>();
    private Session session;
    private Integer userId;

    @Resource
    public void setUserInfoService(UserInfoService userInfoService) {
        WebSocket.userInfoService = userInfoService;
    }
    @Resource
    public void setRedisCache(RedisCache redisCache) {
        WebSocket.redisCache = redisCache;
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) throws IOException {
        this.session = session;
        // 获取用户ID
        String str = JwtUtil.parseJWT(token).getSubject();
        userId = Integer.valueOf(str);
        //chatServers.add(this);
        onlineUsers.put(userId, session);
        // 将用户状态改为在线状态
        userInfoService.changeOnlineStatus(userId, OnlineStatusEnum.OLINE.getCode());
        List<Message> messageList = redisCache.getCacheList(String.valueOf(userId));
        // 如果用户存在未接收的消息，则发送给用户
        if(!messageList.isEmpty()){
            log.info("666");
            redisCache.removeCacheList(String.valueOf(userId));
            Message message = Message.builder()
                    .content(messageList)
                    .type(Message.MESSAGE_LIST)
                    .build();
            session.getBasicRemote().sendText(JSON.toJSONString(message));
        }
        log.info("上线用户ID: {}", userId);
        log.info("在线用户数: {}", onlineUsers.size());
    }
    @OnMessage
    public void onMessage(Session session, String jsonStr){
        log.info("【websocket消息】收到消息:{}",jsonStr);
        // 将字符串转换成类对象
        Message message = JSON.parseObject(jsonStr, Message.class);
        // 将消息的发送对象找出
        Session friendSession = onlineUsers.get(message.getFriendUserId());
        // 将朋友id找出并存储
        Integer friendUserId = message.getFriendUserId();
        // 设置消息发送者设置为发送者
        message.setFriendUserId(userId);
        jsonStr = JSON.toJSONString(message);
        // 如果朋友在线，则发送给朋友，如果不存在，则将消息存在redis个人消息表中
        if(friendSession != null) {
            friendSession.getAsyncRemote().sendText(jsonStr);
        } else {
            redisCache.rPushCacheOne(String.valueOf(friendUserId), message);
        }
        // 将消息发回发送方，并将标识改为发送成功确认标识
        message.setType(Message.MESSAGE_ACCEPT);
        jsonStr = JSON.toJSONString(message);
        this.session.getAsyncRemote().sendText(jsonStr);
        log.info("发送结束ID: {}", userId);
    }
    @OnClose
    public void onClose(Session session) {
        // 将该session关闭
        onlineUsers.remove(this.userId);
        // 将用户在线状态改为离线
        userInfoService.changeOnlineStatus(this.userId, OnlineStatusEnum.ABSENT.getCode());
        log.info("[websocket消息]链接断开,当前总数为:{}",onlineUsers.size());
    }
    /**
     * 当通信发生异常：打印错误日志
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
}
